<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, computed, watch } from 'vue';
import * as echarts from 'echarts';
import 'echarts-gl';
import {ChartDataItem} from "api/types/homepage";
import {useHomepageStore} from "@/stores/homepage"; // 引入 echarts-gl 以支持 3D 图表

const chartRef = ref<HTMLElement | null>(null);
let peiChart: echarts.ECharts | null = null;


// 使用 homepage store
const homepageStore = useHomepageStore();

// 数据处理 - 添加默认值
// const rawData = computed<ChartDataItem[]>(() => {
//   console.log('pie3D 原始数据', homepageStore.chartData);
//   return homepageStore.chartData?.pie01 || [];
// });
const rawData = computed<ChartDataItem[]>(() => {
  // 如果 homepageStore.chartData?.pie01 存在且为数组，则处理
  if (homepageStore.gepResults?.district) {
    // 获取第一条数据（铅山县数据）
    const data = homepageStore.gepResults.district;
    console.log('pie3D 处理后的数据', data);
    if (data) {
      return [
        {
          name: "物质产品",
          value: parseFloat(data.material) || 0
        },
        {
          name: "调节服务",
          value: parseFloat(data.regulation) || 0
        },
        {
          name: "文化服务",
          value: parseFloat(data.culture) || 0
        }
      ];
    }
  }

  // 否则返回空数组
  return [];
});



// 定义颜色列表
const colorList = [
  'rgba(42,210,241,0.5)',   // 物质产品颜色
  'rgba(57,236,155,0.5)',   // 调节服务颜色
  'rgba(95, 144, 110, 0.5)' // 文化服务颜色
];

// 根据 rawData 生成 dataList
const dataList = computed(() => {
  return rawData.value.map((item, index) => {
    // 判断是否需要转换为亿元
    if (item.value >= 10000) {
      // 转换为亿元并保留两位小数
      return {
        name: item.name,
        val: Number((item.value / 10000).toFixed(2)),
        unit: '亿元',
        itemStyle: {
          color: colorList[index % colorList.length] // 根据索引循环使用颜色
        }
      };
    } else {
      // 保持万元单位并保留两位小数
      return {
        name: item.name,
        val: Number(item.value.toFixed(2)),
        unit: '万元',
        itemStyle: {
          color: colorList[index % colorList.length] // 根据索引循环使用颜色
        }
      };
    }
  });
});

console.log("dataList",dataList)

const heightProportion = 0.2 // 柱状扇形的高度比例

// 生成扇形的曲面参数方程，用于 series-surface.parametricEquation
function getParametricEquation(startRatio: number, endRatio: number, isSelected: boolean, isHovered: boolean, k: number, height: number) {
  // 计算
  let midRatio = (startRatio + endRatio) / 3;

  let startRadian = startRatio * Math.PI * 2;
  let endRadian = endRatio * Math.PI * 2;
  let midRadian = midRatio * Math.PI * 2;

  // 如果只有一个扇形，则不实现选中效果。
  if (startRatio === 0 && endRatio === 1) {
    isSelected = false;
  }

  // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
  k = typeof k !== 'undefined' ? k : 1 / 3;

  // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
  let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
  let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;

  // 计算高亮效果的放大比例（未高亮，则比例为 1）
  let hoverRate = isHovered ? 1.1 : 1;

  // 返回曲面参数方程
  return {
    u: {
      min: -Math.PI,
      max: Math.PI * 3,
      step: Math.PI / 32
    },

    v: {
      min: 0,
      max: Math.PI * 2,
      step: Math.PI / 20
    },

    x: function (u: number, v: number) {
      if (u < startRadian) {
        return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
      }
      if (u > endRadian) {
        return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
      }
      return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
    },

    y: function (u: number, v: number) {
      if (u < startRadian) {
        return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
      }
      if (u > endRadian) {
        return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
      }
      return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
    },

    z: function (u: number, v: number) {
      if (u < -Math.PI * 0.5) {
        return Math.sin(u);
      }
      if (u > Math.PI * 2.5) {
        return Math.sin(u);
      }
      return Math.sin(v) > 0 ? heightProportion * height : -1;
    }
  };
}

// 生成模拟 3D 饼图的配置项
function getPie3D(pieData: any[], internalDiameterRatio: number) {
  let series: any[] = [];
  let sumValue = 0;
  let startValue = 0;
  let endValue = 0;
  let linesSeries: any[] = []; // line3D模拟label指示线
  let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3;

  // 为每一个饼图数据，生成一个 series-surface 配置
  for (let i = 0; i < pieData.length; i++) {
    sumValue += pieData[i].value;

    let seriesItem: any = {
      name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
      type: 'surface',
      parametric: true,
      wireframe: {
        show: false
      },
      pieData: pieData[i],
      pieStatus: {
        selected: false,
        hovered: false,
        k: k
      },
      itemStyle: {} // 明确声明 itemStyle 避免 TS 报错
    };

    if (typeof pieData[i].itemStyle != 'undefined') {
      let itemStyle: any = {};

      typeof pieData[i].itemStyle.color != 'undefined' ? itemStyle.color = pieData[i].itemStyle.color : null;
      typeof pieData[i].itemStyle.opacity != 'undefined' ? itemStyle.opacity = pieData[i].itemStyle.opacity : null;

      seriesItem.itemStyle = itemStyle;
    }
    series.push(seriesItem);
  }

  // 使用上一次遍历时，计算出的数据和 sumValue，调用 getParametricEquation 函数，
  // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation，也就是实现每一个扇形。
  for (let i = 0; i < series.length; i++) {
    endValue = startValue + series[i].pieData.value;
    series[i].pieData.startRatio = startValue / sumValue;
    series[i].pieData.endRatio = endValue / sumValue;
    series[i].parametricEquation = getParametricEquation(
        series[i].pieData.startRatio,
        series[i].pieData.endRatio,
        false,
        false,
        k,
        series[i].pieData.value
    );

    startValue = endValue;

    // 计算label指示线的起始和终点位置
    let midRadian = (series[i].pieData.endRatio + series[i].pieData.startRatio) * Math.PI;
    let posX = Math.cos(midRadian) * (1 + Math.cos(Math.PI / 2));
    let posY = Math.sin(midRadian) * (1 + Math.cos(Math.PI / 2));
    let posZ = Math.log(Math.abs(series[i].pieData.value + 1)) * 0.1;
    let flag = ((midRadian >= 0 && midRadian <= Math.PI / 2) || (midRadian >= 3 * Math.PI / 2 && midRadian <= Math.PI * 2)) ? 1 : -1;
    let color = pieData[i].itemStyle?.color || '#ffffff'; // 添加默认颜色
    let turningPosArr = [posX * (1.8) + (i * 0.1 * flag) + (flag < 0 ? -0.5 : 0), posY * (1.8) + (i * 0.1 * flag) + (flag < 0 ? -0.5 : 0), posZ * (2)]
    let endPosArr = [posX * (1.9) + (i * 0.1 * flag) + (flag < 0 ? -0.5 : 0), posY * (1.9) + (i * 0.1 * flag) + (flag < 0 ? -0.5 : 0), posZ * (6)]

    linesSeries.push({
          type: 'line3D',
          lineStyle: {
            color: color,
          },
          data: [[posX, posY, posZ], turningPosArr, endPosArr]
        },
        {
          type: 'scatter3D',
          label: {
            show: true,
            distance: 0,
            position: 'center',
            textStyle: {
              color: '#ffffff',
              backgroundColor: color,
              borderWidth: 2,
              fontSize: 14,
              padding: 10,
              borderRadius: 4,
            },
            formatter: '{b}'
          },
          symbolSize: 0,
          // value: endPosArr: 标签在3D空间中的位置坐标
          data: [{ name: series[i].name + '\n' + series[i].pieData.val, value: endPosArr }],
          // data: [{
          //   name: series[i].name + '\n' + series[i].pieData.val +
          //       (series[i].pieData.unit ? series[i].pieData.unit : ''),
          //   value: endPosArr
          // }]
        });
  }
  series = series.concat(linesSeries)

  // 最底下圆盘
  series.push({
    name: 'mouseoutSeries',
    type: 'surface',
    parametric: true,
    wireframe: {
      show: false,
    },
    itemStyle: {
      opacity: 1,
      color: 'rgb(24,76,80)',
    },
    parametricEquation: {
      u: {
        min: 0,
        max: Math.PI * 2,
        step: Math.PI / 20,
      },
      v: {
        min: 0,
        max: Math.PI,
        step: Math.PI / 20,
      },
      x: function (u: number, v: number) {
        return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2;
      },
      y: function (u: number, v: number) {
        return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2;
      },
      z: function (u: number, v: number) {
        return Math.cos(v) > 0 ? -0 : -1.5;
      },
    },
  });
  return series;
}

const renderPieChart = (dataList: any) => {
  if (chartRef.value) {
    peiChart = echarts.init(chartRef.value);

    let total = 0;
    console.log("dataList", dataList.value);
    dataList.value.forEach((item: any) => {
      total += item.val;
    });

    // 保留两位小数
    const totalFormatted = Number(total.toFixed(2));

    const series = getPie3D(dataList.value.map((item: any) => {
      // 创建新的对象避免修改原始数据，并同时保留 val 和 value
      return {
        ...item,
        value: Number((item.val / total * 100).toFixed(2)),
      };
    }), 0.8);

    // 准备待返回的配置项，把准备好的 legendData、series 传入。
    const option = {
      legend: {
        tooltip: {
          show: true,
        },
        data: dataList.value.map((item: any) => item.name),
        top: '15%',              // 图例距离容器顶部的距离
        right: '5%',            // 图例距离容器右侧的距离
        orient: 'vertical',     // 图例竖向排列
        icon: 'circle',         // 图例项的图标形状
        itemGap: 20,            // 图例项之间的间距
        textStyle: {
          color: '#fff',  // 图例文字颜色
          fontSize: 14,   // 图例文字大小
        },
      },
      animation: true,
      title: [
        {
          x: 'center',
          top: '57%',
          left: '36.5%',
          text: totalFormatted, // 使用格式化后的总值
          textStyle: {
            color: '#fff',
            fontSize: 18,
            fontWeight: 'bold'
          },
        },
        {
          x: 'center',
          top: '65%',
          left: '36.5%',
          text: '生态价值',
          textStyle: {
            color: '#fff',
            fontSize: 16,
            fontWeight: 400
          },
        },
      ],
      // backgroundColor: '#000d4a',
      labelLine: {
        show: true,
        lineStyle: {
          color: '#7BC0CB',
        },
      },
      label: {
        show: false,
      },
      xAxis3D: {
        min: -1.5,
        max: 1.5,
      },
      yAxis3D: {
        min: -1.5,
        max: 1.5,
      },
      zAxis3D: {
        min: -1,
        max: 1,
      },
      grid3D: {
        show: false,                 // 是否显示三维笛卡尔坐标系
        boxHeight: 4,                // 3D图表的高度
        left: '8%',                  // 3D坐标系距离容器左侧的距离
        top: '22%',                  // 3D坐标系距离容器顶部的距离
        width: '70%',                // 3D坐标系的宽度，留出右侧空间给图例
        height: '90%',               // 3D坐标系的高度
        viewControl: {
          distance: 130,             // 视距，值越小图形越大，可调整图形在页面上的大小
          alpha: 25,                 // alpha角度（绕x轴旋转的角度），用于调整3D图表的上下视角
          beta: 60,                  // beta角度（绕y轴旋转的角度），用于调整3D图表的左右视角
          autoRotate: true,          // 是否开启自动旋转
          autoRotateSpeed: 2,        // 自动旋转速度
          autoRotateDirection: 'cw', // 自动旋转方向，'cw'为顺时针，'ccw'为逆时针
          autoRotateAfterStill: 3,   // 静止多少秒后开始自动旋转
          minAlpha: -90,             // alpha角度的最小值
          maxAlpha: 90,              // alpha角度的最大值
          minBeta: -Infinity,        // beta角度的最小值
          maxBeta: Infinity,         // beta角度的最大值
        },
      },
      series: series,
    };

    peiChart.setOption(option);
  }
};


// 监听数据变化，更新图表
watch(dataList, () => {
  renderPieChart(dataList);
});


// 在组件挂载后执行
onMounted(() => {
  // 延迟初始化图表，以确保 DOM 元素已经渲染完成
  setTimeout(() => {
    console.log("pie3D dataList", dataList.value);
    renderPieChart(dataList);
  }, 200);
});

onBeforeUnmount(() => {
  // 在组件销毁前执行
  // 清理图表实例
  if (peiChart) {
    peiChart.dispose();
    peiChart = null;
  }
})
</script>

<template>
  <!-- 引用图表的 DOM 元素，并设置样式 -->
  <div ref="chartRef" style="width: 100%; height: 100%;"></div>
</template>

<style scoped>
/* 你可以根据需要添加样式 */
</style>
